package org.jiajie.coffeecodes.ali;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;

/**
 * SimpleDateFormat 线程安全性
 *
 * @author jay
 */
public class SdfTest1 {

    /**
     * 定义一个全局的 SimpleDateFormat
     */
    private static SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    /**
     * 使用 ThreadFactoryBuilder 定义一个线程池
     */
    private static ThreadFactory namedThreadFactory = new ThreadFactoryBuilder().setNameFormat("demo-pool-%d").build();

    private static ExecutorService pool = new ThreadPoolExecutor(5, 200,
            0L, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(1024),
            namedThreadFactory,
            new ThreadPoolExecutor.AbortPolicy());

    /**
     * 定义一个 CountDownLatch，保证所有子线程执行之后主线程再执行
     */
    private static CountDownLatch countDownLatch = new CountDownLatch(100);


    public static void main(String[] args) throws InterruptedException {
//        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));
//        System.out.println(simpleDateFormat.format(Calendar.getInstance().getTime()));
        // 定义一个线程安全的HashSet
        Set<String> dates = Collections.synchronizedSet(new HashSet<>());
        for (int i = 0; i < 100; i++) {
            // 获取当前时间
            Calendar calendar = Calendar.getInstance();
            int finalI = i;
            pool.execute(() -> {
                // add lock
                synchronized (simpleDateFormat) {
                    // 时间增加
                    calendar.add(Calendar.DATE, finalI);
                    // 通过 simpleDateFormat 把时间转换成字符串
                    String dateString = simpleDateFormat.format(calendar.getTime());
                    // 把字符串放入 Set 中
                    dates.add(dateString);
                    // countDown
                    countDownLatch.countDown();
                }
            });
        }
        // 阻塞，直到 countDown 数量为 0
        countDownLatch.await();
        // 输出后重后的时间个数
        System.out.println(dates.size());
    }

}
